#coding=utf-8
#===============================================================================
# 当无法使用socket连接的时候，使用HTTP方式与客户端通信，得到其地址
#===============================================================================
from twisted.protocols import basic
from twisted.internet import protocol, reactor

from twisted.web import http

class HttpEchoProtocol(basic.LineReceiver):
    
    def __init__(self):
        self.lines = []
        self.gotRequest = False       
        self.peers = []
        #print dir(basic.LineReceiver)
        """
        ['MAX_LENGTH', '_LineReceiver__buffer', '__doc__', '__implemented__', '__module__', '__providedBy__', '__provides__', 'clearLineBuffer', 'connected', 'connectionLost', 'connectionMade', 'dataReceived', 
        'delimiter', 'lineLengthExceeded', 'lineReceived', 'line_mode', 'makeConnection', 'pauseProducing', 
        'paused', 'rawDataReceived', 'resumeProducing', 'sendLine', 'setLineMode', 'setRawMode', 'stopProducing', 'transport']
        """
    
    def connectionMade(self):
        temp = self.transport
        #得到远程客户端的地址
        peer = temp.getPeer()
        print "make connection from %s:%d"%(peer.host, peer.port)
        peer = (peer.host, peer.port)
        self.peers.append(peer)

    def lineReceived(self, line):
        #self.transport, dir(self.transport)
        """
        ['SEND_LIMIT', 'TLS', '__class__', '__delattr__','__dict__','__doc__','__getattribute__', 
        '__getstate__', '__hash__', '__implemented__', '__init__', '__module__', '__new__', 
        '__providedBy__', '__provides__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
        '__setstate__', '__str__', '__weakref__', '_closeSocket', '_closeWriteConnection', 
        '_postLoseConnection', '_socketShutdownMethod', '_tempDataBuffer', '_tempDataLen', 
        '_writeDisconnected', '_writeDisconnecting', 'bufferSize', 'client', 'connected', 
        'connectionLost', 'dataBuffer', 'disconnected', 'disconnecting', 'doRead', 'doWrite', 
        'fileno', 'getHandle', 'getHost', 'getPeer', 'getTcpKeepAlive', 'getTcpNoDelay', 
        'hostname', 'logPrefix', 'logstr', 'loseConnection', 'loseWriteConnection', 'offset',
        'pauseProducing', 'producer', 'producerPaused', 'protocol', 'reactor', 'readConnectionLost', 
        'registerProducer', 'repstr', 'resumeProducing', 'server', 'sessionno', 'setTcpKeepAlive',
        'setTcpNoDelay', 'socket', 'startReading', 'startTLS', 'startWriting', 'stopConsuming', 
        'stopProducing', 'stopReading', 'stopWriting', 'streamingProducer', 'unregisterProducer', 
        'write', 'writeConnectionLost', 'writeSequence', 'writeSomeData']
        """        
        self.lines.append(line)
        if not line and not self.gotRequest:
            self.sendResponse()
            self.gotRequest = True

    def sendResponse(self):
        responseBody = "You said:\r\n\r\n" + "\r\n".join(self.lines)

        for i in self.peers:
            responseBody += "\n"+i[0]+":"+str(i[1])

        self.sendLine("HTTP/1.0 200 OK")
        self.sendLine("Content-Type: text/plain")
        self.sendLine("Content-Length: %i" % len(responseBody))
        self.sendLine("")
        self.transport.write(responseBody)
        self.transport.loseConnection()
        
def renderHomePage(request):
    colors = 'red', 'blue', 'green'
    flavors = 'vanilla', 'chocolate', 'strawberry', 'coffee'
    request.write("""
    <html>
    <head>
      <title>Form Test</html>
    </head>
    <body>
      <form action='posthandler' method='post'>
        Your name:
        <p>
          <input type='text' name='name'>
        </p>
        What's your favorite color?
        <p>
    """)
    for color in colors:
        request.write(
            "<input type='radio' name='color' value='%s'>%s<br />" % (
            color, color.capitalize()))
    request.write("""
        </p>
        What kinds of ice cream do you like?
        <p>
        """)
    for flavor in flavors:
        request.write(
            "<input type='checkbox' name='flavor' value='%s'>%s<br />" % (
            flavor, flavor.capitalize()))
    request.write("""
        </p>
        <input type='submit' />
      </form>
    </body>
    </html>
    """)
    request.finish()

def stunPost(request):
    #deal with the post request
    """
    正确，返回格式
    status:0
    ip:10.1.1.1
    port:1000
    ===========
    错误， 返回格式
    status:-1
    error:......
    
    """
    """
    for key, values in request.args.items():
        print key, values#TODO LOG
        request.write("<h2>%s</h2>" % key)
        request.write("<ul>")
        for value in values:
            request.write("<li>%s</li>" % value)
        request.write("</ul>")
    """
    status = -1
    error  = ""
    spliter = "\r\n"
    
    peer = request.transport.getPeer()
    ip   = peer.host
    port = peer.port
    
    key = "index"#find the index's value
    values = request.args.get(key)
    if not values:
        #参数为空
        status = 0
        
        request.write("status=0"+spliter)
        request.write("ip="+ip+spliter)
        request.write("port="+str(port)+spliter)
        #status = -1
        #error  = "缺少参数!"
    else:
        value = values[0]
        print type(value)#TODO LOG
        if int(value) not in [1, 2, 3]:
            #参数错误
            status = -1
            error  = "index参数错误"
        else:
            status = 0
            
            request.write("status=0"+spliter)
            request.write("ip="+ip+spliter)
            request.write("port="+str(port)+spliter)
    
    if status == -1:
        request.write("status=-1"+spliter)
        request.write("error="+error+spliter)            
    
    request.finish()

class FunctionHandledRequest(http.Request):
    pageHandlers = {
        '/login.jl': renderHomePage,#TODO add login process
        '/stun.jl' : stunPost,    #use http method implement some function of stun protocol
        }
    
    def process(self):
        self.setHeader('Content-Type', 'text/plain')#return some infprmation of the client to themselves
        print self.path#TODO LOG
        if self.pageHandlers.has_key(self.path):
            handler = self.pageHandlers[self.path]
            handler(self)
        else:
            self.setResponseCode(http.NOT_FOUND)
            self.write("<h1>Not Found</h1>Sorry, no such page.")
            self.finish()

class MyHttp(http.HTTPChannel):
    #requestFactory = MyRequestHandler
    requestFactory = FunctionHandledRequest

class MyHttpFactory(http.HTTPFactory):
    protocol = MyHttp
    
if __name__ == "__main__":
    from twisted.internet import reactor
    reactor.listenTCP(8000, MyHttpFactory())
    reactor.run()

"""
f = protocol.ServerFactory()
f.protocol = HttpEchoProtocol
reactor.listenTCP(8000, f)
reactor.run()
"""